package cn.edu.cug.cs.gtl.oi.inventor.demo;

import cn.edu.cug.cs.gtl.oi.utils.Example;
import com.openinventor.inventor.*;
import com.openinventor.inventor.nodes.*;
import com.openinventor.inventor.viewercomponents.SoCameraInteractor;
import com.openinventor.inventor.viewercomponents.awt.IViewerExaminer;

import java.awt.*;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

import  cn.edu.cug.cs.gtl.oi.utils.ViewerComponentsFactory;

public class BSCurve extends Example {

    private IViewerExaminer myViewer;

    public static void main(String []argv) {
        BSCurve example = new BSCurve();
        example.demoMain("BSCurve");
    }

    @Override
    public void start() {
        myViewer = ViewerComponentsFactory.createViewerExaminer();

        // Create the scene graph for the floor texture
        SoTexture2 floor_texture = new SoTexture2();
        floor_texture.filename.setValue("$OIVJHOME/data/textures/rgb/oak.rgb");

        // Create the scene graph for the floor
        URL url_floor = getURL(SoPreferences.getValue("OIVJHOME") + "/data/models/Floor.iv");
        if (url_floor == null) return;

        SoSeparator floor = new SoSeparator();
        SoTranslation xlate = new SoTranslation();
        SoRotation rot = new SoRotation();
        SoScale scale = new SoScale();

        SoInput in = new SoInput();
        in.openURL(url_floor);
        SoNode result = SoDB.readNode(in);
        xlate.translation.setValue(new SbVec3f(-12, -5, -5));
        scale.scaleFactor.setValue(new SbVec3f(2, 1, 2));
        rot.rotation.setValue(new SbRotation(new SbVec3f(0, 1, 0), (float)(Math.PI/2)));
        {
            floor.addChild(rot);
            floor.addChild(xlate);
            floor.addChild(scale);
            floor.addChild(result);
        }

        // Create the scene graph for the heart
        SoSeparator heart = new SoSeparator();
        SoSeparator curveSep = makeCurve();
        SoLightModel lmodel = new SoLightModel();
        SoBaseColor clr = new SoBaseColor();

        lmodel.model.setValue(SoLightModel.Models.BASE_COLOR);
        clr.rgb.setValue(new SbColor(1.0F, 0.0F, 0.1F));
        {
            heart.addChild(lmodel);
            heart.addChild(clr);
            heart.addChild(curveSep);
        }

        // Create the scene graph for the heart's shadow
        SoSeparator shadow = new SoSeparator();
        SoLightModel shmdl  = new SoLightModel();
        SoMaterial shmtl  = new SoMaterial();
        SoBaseColor shclr  = new SoBaseColor();
        SoTranslation shxl  = new SoTranslation();
        SoScale shscl  = new SoScale();

        shmdl.model.setValue(SoLightModel.Models.BASE_COLOR);
        shclr.rgb.setValue(new SbColor(0.21F, 0.15F, 0.09F));
        shmtl.transparency.setValue(0.5F);
        shxl.translation.setValue(new SbVec3f(0, -4.9F, 0));
        shscl.scaleFactor.setValue(new SbVec3f(1, 0.01F, 1));
        {
            shadow.addChild(shmtl);
            shadow.addChild(shmdl);
            shadow.addChild(shclr);
            shadow.addChild(shxl);
            shadow.addChild(shscl);
            shadow.addChild(curveSep);
        }

        SoSeparator root  = new SoSeparator();
        { // assemble scene graph
            root.addChild(heart);
            root.addChild(floor_texture);
            root.addChild(floor);
            root.addChild(shadow);
        }

        myViewer.setSceneGraph(root);
        SoCameraInteractor interactor = myViewer.getRenderArea().getSceneInteractor().getCameraInteractor();
        interactor.setPosition(new SbVec3f(-6, 8, 20));
        interactor.pointAt(new SbVec3f(0, -2, -4));

        final Component component = myViewer.getComponent();
        component.setPreferredSize(new java.awt.Dimension(600, 500));
        setLayout(new BorderLayout());
        add(component);
    }

    @Override
    public void stop()
    {
        myViewer.dispose();
    }

    // Create the nodes needed for the B-Spline curve.
    SoSeparator makeCurve() {
        // The control points for this curve
        float pts[][] = {
                { 4, -6,  6},
                {-4,  1,  0},
                {-1.5F,  5, -6},
                { 0,  2, -2},
                { 1,  5, -6},
                { 4,  1,  0},
                {-4, -6,  6}
        };

        // The knot vector
        float knots[] = {1, 2, 3, 4, 5, 5, 6, 7, 8, 9};

        SoSeparator curveSep = new SoSeparator();

        // Set the draw style of the curve.
        SoDrawStyle drawStyle  = new SoDrawStyle();
        drawStyle.lineWidth.setValue(4);
        curveSep.addChild(drawStyle);

        // Define the NURBS curve including the control points
        // and a complexity.
        SoComplexity complexity = new SoComplexity();
        SoCoordinate3 controlPts = new SoCoordinate3();
        SoNurbsCurve curve = new SoNurbsCurve();
        complexity.value.setValue(0.8F);
        controlPts.point.setValues(0, pts);
        curve.numControlPoints.setValue(7);
        curve.knotVector.setValues(0, knots);
        curveSep.addChild(complexity);
        curveSep.addChild(controlPts);
        curveSep.addChild(curve);

        return curveSep;
    }

    private URL getURL(String fileName) {
        URL url = null;
        try {
            url = new URL("file:"+(new File(fileName)).getAbsolutePath()) ;
        }
        catch (MalformedURLException exc) {
            System.err.println(exc + " : (" + url + ") " + fileName + " invalid URL");
            url = null;
        }
        catch (Exception e) {
            System.err.println(e + " : cant load File "+ fileName);
            url = null;
        }
        return url;
    }

}
